using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.BizTalk.Component.Interop;
using Microsoft.BizTalk.Message.Interop;
using System.IO;
using Microsoft.BizTalk.XPath;

using TCPSoftware.BizTalk.PipelineComponents.MockPipelineComponent;


namespace TCPSoftware.BizTalk.PipelineComponents.MockPipelineComponent
{
    public partial class MockPipelineAssemblerComponent : IAssemblerComponent
    {
        #region Helper Methods
        //Clones a full IBaseMessage except for the body part: 
        protected IBaseMessage cloneIBaseMessage(IBaseMessageFactory msgFactory, IBaseMessage srcMessage)
        {
            return cloneIBaseMessage(msgFactory, srcMessage, srcMessage.BodyPart.Data);
        }

        //Clones a full IBaseMessage except for the body part and assigns the new body stream: 
        protected IBaseMessage cloneIBaseMessage(IBaseMessageFactory msgFactory, IBaseMessage srcMessage,
                                       Stream newBodyDataStream)
        {
            IBaseMessage resultMsg = msgFactory.CreateMessage();

            //copy context by reference: 
            resultMsg.Context = srcMessage.Context;

            //copy all non-body parts by reference: 
            copyAllNonBodyMsgParts(srcMessage, resultMsg);

            //create new body part: 
            IBaseMessagePart body = msgFactory.CreateMessagePart();
            body.PartProperties = srcMessage.BodyPart.PartProperties;
            body.Data = newBodyDataStream;

            //add it to the result message: 
            resultMsg.AddPart(srcMessage.BodyPartName, body, true);

            return resultMsg;
        }

        protected void copyAllNonBodyMsgParts(IBaseMessage src, IBaseMessage dest)
        {
            for (int i = 0; i < src.PartCount; i++)
            {
                //fetch part from original message: 
                string partname;
                IBaseMessagePart part = src.GetPartByIndex(i, out partname);

                //copy it to destination message: 
                if (partname != src.BodyPartName)
                    dest.AddPart(partname, part, false);
            }
        }
        #endregion

        private Dictionary<String,Object> innerBag = new Dictionary<string,object>();
        private Evaluator.Boo.BooScriptAssemblerManager parser;
        #region IComponent Members

        #endregion

        #region IAssemblerComponent Members

        public void AddDocument(IPipelineContext pContext, IBaseMessage pInMsg)
        {
            if (isEnabled)
            {
                if (parser == null) { parser = new Evaluator.Boo.BooScriptAssemblerManager(innerBag); }

                parser = new Evaluator.Boo.BooScriptAssemblerManager(innerBag);
                parser.AddDocument(pContext, pInMsg);
            }
            else
            {
                storage = new Queue<IBaseMessage>();
                storage.Enqueue(pInMsg);
            }
        }

        private Queue<IBaseMessage> storage;

        public IBaseMessage Assemble(IPipelineContext pContext)
        {
            if (isEnabled)
            {
                if (parser == null) { parser = new Evaluator.Boo.BooScriptAssemblerManager(innerBag); }
                return parser.Assemble(pContext);
            }
            else { return storage.Count==0?null:storage.Dequeue(); };
        }

        #endregion
    }
}
